#include "StdAfx.h"
#include "DrawComboBox.h"
#include "DrawBaseList.h"
#include "ResourceHelper.h"
namespace UILib
{
    class CComboBoxItem : public CListItemBase
    {
    public:
        CComboBoxItem(const PUIRect pRect, const UINT uParentID, const UINT uID, const int nStatusCount = 4, ViewListener* pListener = NULL )
            : CListItemBase(pRect, uParentID, uID, nStatusCount, pListener )
        {
            m_clText = RGB(0Xd3, 0Xd3, 0Xd5);
            m_clHover = RGB(237, 70, 130);
            m_clSel = RGB(0x6B, 0x68, 0x74);
        };
        virtual ~CComboBoxItem(void){
        };
        virtual void SetName( const wstring& wszFileName, void* pUser ){
            CListItemBase::SetName( wszFileName, pUser );
            //m_clHover = (COLORREF)pUser;
        }

        virtual void DrawElement( const HDC hDC, const RECT &rcPaint )
        {
            CDrawView::bNeedInvalidate_ = false;
            if ( m_StatusCount == 0 || !IsVisible() )
            {
                return;
            }

            RECT rcElem;
            CDrawView::GetRECT(rcElem);
            if ( !CDrawView::HitDraw(rcPaint, rcElem) )
            {
                return;
            }

            rcElem.right = rcElem.right - 9;
            {
                HFONT hfont = ::CreateFontIndirect(&m_lf);
                HFONT holdFont = (HFONT)::SelectObject(hDC, hfont);
                if (  (eStatus_ != Elem_Normal || m_bSel) )
                {
                     COLORREF cl = m_clHover;
                     if ( m_bSel )
                     {
                         cl = m_clSel;
                     }
                    HBRUSH hBrush = ::CreateSolidBrush( cl );
                    ::FillRect(hDC, &rcElem, hBrush);
                    ::DeleteObject(hBrush);
                }

                COLORREF cl = m_clText;
                COLORREF oldColor = ::SetTextColor(hDC, cl );
                int oldbkgMode = ::SetBkMode(hDC, TRANSPARENT);
                if (!m_wszName.empty())
                {
                    rcElem.left += 7;
                    ::DrawText(hDC, m_wszName.c_str(), -1, &rcElem, DT_SINGLELINE | DT_VCENTER |DT_NOPREFIX | DT_LEFT| DT_END_ELLIPSIS );
                }
                ::SetBkMode(hDC, oldbkgMode);
                ::SelectObject(hDC, holdFont);
                ::SetTextColor(hDC, oldColor);
                ::DeleteObject(hfont);
            }
        };
    };
    typedef CBaseListT<CComboBoxItem> CComboBoxTest;
    ////////////////////////////////////////////////////////////////////////////////////
    CDrawComboBox::CDrawComboBox(void) : CDrawView( NULL, -1, NULL )
        , m_hWnd(NULL)
        , m_pBitMap(NULL)\
        , m_pArrow(NULL)\
        , m_StatusCount(4)\
        , m_nSel(-1)\
        , m_color(RGB(128, 128, 128))\
        , m_colorSel(0xFFFFFF)\
        , m_pComDlg(NULL)\
        , clListbkg_(RGB(40, 39, 47))\
        , clListHover_(RGB(0, 0, 0))\
        , bmpScroll_(NULL)
    {
        memset(&m_szSplit, 0, sizeof(SplitPos));
        memset(&m_lf, 0, sizeof(LOGFONT));
    }

    CDrawComboBox::CDrawComboBox( HWND hWnd, Bitmap* pBitmap, Bitmap* pIcon, const PUIRect pRect , const PSplitPos pSplit /*= NULL*/, const UINT uID /*= -1*/, const int nStatusCount /*= 4\ */, ViewListener* pListener /*= NULL*/ )
        : CDrawView( pRect, uID, pListener )\
        , m_hWnd(hWnd)
        , m_pBitMap(pBitmap)\
        , m_pArrow(pIcon)\
        , m_StatusCount(nStatusCount)\
        , m_nSel(-1)\
        , m_color(RGB(128, 128, 128))\
        , m_colorSel(0xFFFFFF)\
        , m_pComDlg(NULL)
        , clListbkg_(RGB(40, 39, 47))\
        , clListHover_(RGB(255, 255, 255))\
        , bmpScroll_(NULL)
    {
        if ( pSplit )
        {
            memcpy(&m_szSplit, pSplit, sizeof(SplitPos) );
        }
        else
        {
            memset(&m_szSplit, 0, sizeof(SplitPos));
        }
        memset(&m_lf, 0, sizeof(LOGFONT));
    }
    CDrawComboBox::~CDrawComboBox( void )
    {

    }

    void CDrawComboBox::DrawElement( const HDC hDC, const RECT &rcPaint )
    {
        if ( m_pBitMap == NULL || m_pArrow == NULL || !IsVisible() )
        {
            return;
        }
        CDrawView::bNeedInvalidate_ = false;

        RECT rcElmem = {0};
        CDrawView::GetRECT(rcElmem);
        SIZE szElem = { rcElmem.right - rcElmem.left, rcElmem.bottom - rcElmem.top };

        Elem_Status eStatus = CDrawView::GetStatus();
        Graphics graph(hDC);
        {
            int nW = m_pBitMap->GetWidth();
            int nH = m_pBitMap->GetHeight();
            int nStatusW = nW/m_StatusCount;
            if ( (int)eStatus > m_StatusCount - 1 )
            {
                eStatus = (Elem_Status)(m_StatusCount - 1);
            }
            //Draw Bkg
            Rect rcBkgDestL(rcElmem.left, rcElmem.top, m_szSplit.lBegin, szElem.cy );
            Rect rcBkgDestM(rcElmem.left + m_szSplit.lBegin, rcElmem.top, szElem.cx - ( nStatusW - (m_szSplit.lEnd - m_szSplit.lBegin) ), szElem.cy );
            Rect rcBkgDestR(rcElmem.right - ((nStatusW) - m_szSplit.lEnd), rcElmem.top, (nStatusW) - m_szSplit.lEnd, szElem.cy );
            graph.DrawImage(m_pBitMap, rcBkgDestL, nStatusW*eStatus, 0, m_szSplit.lBegin, nH, UnitPixel, NULL, NULL, NULL);
            graph.DrawImage(m_pBitMap, rcBkgDestM, nStatusW*eStatus + m_szSplit.lBegin, 0,  m_szSplit.lEnd - m_szSplit.lBegin, nH, UnitPixel, NULL, NULL, NULL);
            graph.DrawImage(m_pBitMap, rcBkgDestR, nStatusW*eStatus + m_szSplit.lEnd, 0, (nStatusW) - m_szSplit.lEnd, nH, UnitPixel, NULL, NULL, NULL);
        }
        //DrawIcon
        {
            int nW = m_pArrow->GetWidth();
            int nH = m_pArrow->GetHeight();

            Rect rcIconDest(rcElmem.right - nW - 10, rcElmem.top + (szElem.cy - nH)/2, nW, nH );
            graph.DrawImage(m_pArrow, rcIconDest, 0, 0, nW, nH, UnitPixel, NULL, NULL, NULL);
        }
        //DrawText
        if ( m_nSel != -1 && m_nSel >=0 && m_nSel < (int)m_vecItem.size() )
        {
            int nW = m_pArrow->GetWidth();
            int nH = m_pArrow->GetHeight();

            wstring wszText = m_vecItem[m_nSel];

            RECT rcText = {rcElmem.left + 10, rcElmem.top, rcElmem.right - nW - 10*2, rcElmem.bottom};

            HFONT hfont = ::CreateFontIndirect(&m_lf);
            HFONT holdFont = (HFONT)::SelectObject(hDC, hfont);
            COLORREF oldColor = ::SetTextColor(hDC, m_color );
            int oldbkgMode = ::SetBkMode(hDC, TRANSPARENT);
            ::DrawText(hDC, wszText.c_str(), -1, &rcText, DT_SINGLELINE | DT_VCENTER |DT_NOPREFIX | DT_LEFT |DT_END_ELLIPSIS );
            ::SetBkMode(hDC, oldbkgMode);
            ::SelectObject(hDC, holdFont);
            ::SetTextColor(hDC, oldColor);
            ::DeleteObject(hfont);
        }
    }

    void CDrawComboBox::AppendText( const wstring wszText )
    {
        m_vecItem.push_back(wszText);
    }

    void CDrawComboBox::Clear()
    {
        m_vecItem.clear();
        m_nSel = -1;
    }

    void CDrawComboBox::SetSel( const int nSel )
    {
        m_nSel = nSel;
        CDrawView::ForceInvalidate();
    }

    void CDrawComboBox::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, HWND hWnd, BOOL& bHandled )
    {
        if (!IsVisible() && !IsEnable() )
        {
            return;
        }
        RECT rcElmem = {0};
        CDrawView::GetRECT(rcElmem);

        bool bInElem =  CDrawView::HitCursor( lParam, rcElmem );
        switch( uMsg )
        {
        case WM_MOUSEMOVE :
            {
                if (bInElem)
                {
                    if ( CDrawView::eStatus_ != Elem_Hover && !CDrawView::bLBDown_ )
                    {
                        CDrawView::eStatus_ = Elem_Hover;
                        CDrawView::ForceInvalidate();
                    }
                }
                else
                {
                    if (  CDrawView::eStatus_ != Elem_Normal )
                    {
                        CDrawView::eStatus_ = Elem_Normal;
                        CDrawView::ForceInvalidate();
                    }
                }
            }	
            break;
        case WM_MOUSELEAVE :
            {
                if ( CDrawView::eStatus_ != Elem_Normal && !CDrawView::bLBDown_ )
                {
                    CDrawView::eStatus_ = Elem_Normal;
                    CDrawView::ForceInvalidate();
                }
            }	
            break;
        case WM_LBUTTONDOWN :
            {
                if (  bInElem  )
                {
                    if ( CDrawView::eStatus_ != Elem_Down )
                    {
                        CDrawView::eStatus_ = Elem_Down;
                        CDrawView::ForceInvalidate();
                    }
                    bLBDown_ = true;
                }
            }
            break;
        case WM_LBUTTONUP :
            {
                if (  bInElem )
                {
                    if (  bInElem )
                    {
                        CDrawView::eStatus_ = Elem_Hover;
                    }
                    else
                    {
                        CDrawView::eStatus_ = Elem_Normal;
                    }
                    CDrawView::ForceInvalidate();
                    //POSTMSG
                    if (CDrawView::IsEnable() && CDrawView::IsVisible() && CDrawView::bLBDown_ )
                    {
                        OnClick();
                    }
                }
                if (CDrawView::bLBDown_)
                {
                    //::ReleaseCapture();
                    CDrawView::bLBDown_ = false;
                }
            }
            break;
        }
    }

    void CDrawComboBox::OnClick()
    {
        int nItemCount = (int)m_vecItem.size();

        if (nItemCount == 0 )
        {
            return;
        }
        int nListH = nItemCount*31;
        if ( nListH > 6*31 )
        {
            nListH = 6*31;
        }

        RECT rcElmem;
        CDrawView::GetRECT(rcElmem);
        SIZE szWnd = {rcElmem.right - rcElmem.left, nListH + 6 };
        POINT pt = {rcElmem.left, rcElmem.bottom};
        ::ClientToScreen(m_hWnd, &pt);
        RECT rc = { pt.x, pt.y, pt.x + szWnd.cx, pt.y + szWnd.cy };

        //NeedCreateWmd;
        if ( m_pComDlg == NULL )
        {
           CreateDropDownDlg(rc);
        }
        else
        {
            HWND hWnd = m_pComDlg->Get_HWnd();
            if ( ::IsWindow(hWnd) )
            {
                ::BringWindowToTop(hWnd);
            }
            else
            {
                delete m_pComDlg;
                m_pComDlg = NULL;

                CreateDropDownDlg(rc);
            }
        }
    }

    void CDrawComboBox::SetTextColor( const COLORREF cl, const COLORREF clSel )
    {
        m_color = cl;
        m_colorSel = clSel;
    }

    void CDrawComboBox::SetTextFont( const LOGFONT& lf )
    {
        memcpy(&m_lf, &lf, sizeof(LOGFONT));
    }

    void CDrawComboBox::Erase( const int nIndex )
    {
        if ( m_nSel >= nIndex )
        {
            m_nSel--;
        }
        if ( m_nSel < 0 )
        {
            m_nSel = 0;
        }
        if ( nIndex >=0 && nIndex < (int)m_vecItem.size() )
        {
            m_vecItem.erase( m_vecItem.begin() + nIndex);
        }
    }

    void CDrawComboBox::CreateDropDownDlg( RECT& rc )
    {
        UILib::IUIDialog* pDlg = UILib::CUIFactory::Instance()->Get_Dialog();

        PPopupCustomObserver pDlgObserver = new PopupCustomObserver;

        UILib::PDialogParam pParam = new UILib::DialogParam;
        memcpy(&pParam->_rcWnd, &rc, sizeof(RECT));
        pParam->_bLostFocusClose = true;
        pDlg->Set_CustomObserver(pDlgObserver);
        pDlg->Set_BackgroundColor(clListbkg_);
        pDlg->InitParam(pParam);

        //Add Element
        CDrawUITree* pTree = new CDrawUITree( pDlg->Get_HWnd() );
        pDlg->BindUITree(pTree);

        //Add Element
        UIRect rcList(3, 3, rc.right - rc.left - 3 , rc.bottom - rc.top - 6 );
        SIZE szItem = {rc.right - rc.left - 3, 31};
        CComboBoxTest* pList = new CComboBoxTest(pDlg->Get_HWnd(),&rcList, -1, dynamic_cast<ViewListener*>(this) );
        pList->SetSrollBitmap(NULL, bmpScroll_ );
        pList->SetItemSize(szItem);
        for ( vector<wstring>::iterator it = m_vecItem.begin(); it != m_vecItem.end(); it++ )
        {
            wstring wszText = (*it);
            pList->ApendItem(wszText, (void*)clListHover_);
        }
        pList->PreCaclContainer();
        pList->SetSel(m_nSel);
        pList->Scroll2CurPos(m_nSel);
        pList->ForceInvalidate();
        pTree->AddChildren(pList);

        pDlg->Show(SW_SHOWNORMAL);
        m_pComDlg = pDlg;
    }

    void CDrawComboBox::OnSelChanged( const UINT uorgMsg, const int nSel, const int uID, const bool bSel, void* vData )
    {
        if ( m_pComDlg )
        {
            ::PostMessage( m_pComDlg->Get_HWnd(), WM_CLOSE, 0, 0);
        }

        if ( nSel >= 0 && nSel < (int)m_vecItem.size() )
        {
            SetSel(nSel);
            CDrawView::ForceInvalidate();
            if ( pListener_ )
            {
                (dynamic_cast<ComboBoxListener*>(pListener_))->OnSelChanged( nSel, CDrawView::GetID() );
            }
        }
    }

    void CDrawComboBox::SetDropDownInfo( const COLORREF clBkg, const COLORREF clHover, Bitmap* pScrollBtn )
    {
        clListbkg_ = clBkg;
        clListHover_ = clHover;
        bmpScroll_ = pScrollBtn;
    }
}